package codegen;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.StringWriter;
import java.util.ArrayList;

import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
import org.apache.velocity.exception.ParseErrorException;
import org.apache.velocity.exception.ResourceNotFoundException;


import utils.EntityUtils;
import utils.GenUtils;
import utils.FelipeUtils;
import java.io.FileWriter;
import xmibase.XmiClass;
import xmibase.XmiPackage;

public class VelocityProcessor {

	public Velocity velocity;
	public ArrayList<BlueTemplate> templates;
    public VelocityContext context;
    
    
     public ArrayList<File> listFiles;


     public String templatesPath;
    


	public String outDir;
	public XmiPackage Application;
    

	public VelocityProcessor(String templatesPath, String outDir) {
		this.templatesPath = templatesPath;
		this.outDir = outDir;
		this.listFiles = new ArrayList<File>();
		this.templates = new ArrayList<BlueTemplate>();
		this.context = new VelocityContext();
       
        

      
       

	}

	public void execute(ArrayList<String> listTemplatesRoles) throws Exception {

		velocity.setProperty("file.resource.loader.path", "");
		velocity.init();
		EntityUtils entityUtils = new EntityUtils();
		GenUtils reportBeanUtils = new GenUtils();
                FelipeUtils utils = new FelipeUtils();
		this.context.put("entityUtils", entityUtils);
		this.context.put("reportBeanUtils", reportBeanUtils);
                this.context.put("felipeUtils", utils);
		listFiles(this.templatesPath);
		loadTemplates();
		ArrayList<BlueTemplate> auxFilteredTemplates = new ArrayList<BlueTemplate>();
		auxFilteredTemplates = filterTemplates(listTemplatesRoles);

		for (BlueTemplate tmpBlueTemplate : auxFilteredTemplates) {
			System.out.println("Template: " + tmpBlueTemplate.getName());
			if (true) {
				generateClass(tmpBlueTemplate);
			} else {
				generatePackage(tmpBlueTemplate);
			}

		}
	}



    
    
   

    

     

	public void generatePackage(BlueTemplate tmpBlueTemplate)
			throws ResourceNotFoundException, ParseErrorException, Exception {

        for (XmiPackage pkg : Application.getPackages()) {
			String[] auxModule = pkg.getName().split("\\p{Punct}");
            
			if (auxModule.length > 2) {
               System.out.println(pkg.getName()+"  TESTE");
				StringWriter output = new StringWriter();
				context.put("package", pkg);
				context.put("subPackage", tmpBlueTemplate.getNameSubPackage());

				Template template = velocity.getTemplate(tmpBlueTemplate
						.getAbsolutePath());
				template.merge(context, output);

				FilesParser file = new FilesParser(this.outDir);
				// modulo + SubPKG
				String module_PKG = pkg.getName()
						+ tmpBlueTemplate.getSubPackage();
				String fileName = getFileName(tmpBlueTemplate, "naosei");
				//file.generateFiles(fileName,module_PKG,module_PKG_subPackage, Application.getName(),
						//output.toString());
				System.out.println(module_PKG);
                System.out.println("MUDA");
				context.remove("package");
			}
		}

	}



        //Metodo criado por Felipe Gutierrez


        

        //alterar codigo desse metodo para o original , pois foi alterado anteriormente
	public void generateClass(BlueTemplate tmpBlueTemplate)
			throws ResourceNotFoundException, ParseErrorException, Exception {
		String appName = this.Application.getName();
                FelipeUtils utils = new FelipeUtils();

        

      


		for (XmiClass classe : this.Application.getClasses()) {
                        if(utils.packageName(classe.getPackageName()) != null){
		//	if (classe.getName().equals("Pessoa")) {
				StringWriter output = new StringWriter();
				context.put("class", classe);
				context.put("subPackage", tmpBlueTemplate.getNameSubPackage());
                System.out.println(classe.getName());
                System.out.println(utils.packageName(classe.getPackageName()) + " pacote");
                System.out.println(utils.subPackageName(classe.getPackageName()) + " subpacote");
				Template template = velocity.getTemplate(tmpBlueTemplate
						.getAbsolutePath());
				template.merge(context, output);

				FilesParser file = new FilesParser(this.outDir);
				String classeName = classe.getName();
				// modulo + SubPKG
				String module_PKG_Package = utils.packageName(classe.getPackageName());
                String module_PKG_SubPackage = utils.subPackageName(classe.getPackageName());
                String module_visualization = utils.visualization(classe.getPackageName());
										// file Name
				String fileName = getFileName(tmpBlueTemplate, classe.getName());

				file.generateFiles(fileName, module_PKG_Package, module_PKG_SubPackage,module_visualization, appName, output
						.toString());

				context.remove("class");
			}
		//}
                }
	}

	public String getFileName(BlueTemplate tmpBlueTemplate, String name) {
		return tmpBlueTemplate.getPrefixFileName() + name
				+ tmpBlueTemplate.getSufixFileName() + "."
				+ tmpBlueTemplate.getFileExtention();

	}

	public ArrayList<BlueTemplate> filterTemplates(
			ArrayList<String> listTemplateRoles) {
		ArrayList<BlueTemplate> templateList = new ArrayList<BlueTemplate>();
		for (BlueTemplate template : templates) {
			for (String auxName : listTemplateRoles) {
				if (template.getName().startsWith(auxName)) {
					templateList.add(template);
				}
			}
		}

		return templateList;
	}

	public void loadTemplates() throws ResourceNotFoundException,
			ParseErrorException, Exception {
		for (File file : listFiles) {
			Template template = new Template();
			BlueTemplate blueTemplate = new BlueTemplate();
			setTemplate(blueTemplate, file);
			blueTemplate.setAbsolutePath(file.getAbsolutePath().toString());

			templates.add(blueTemplate);
		}
	}

	private void setTemplate(BlueTemplate blueTemplate, File file)
			throws IOException {
		BufferedReader in = new BufferedReader(new FileReader(file));
		String str = "";
		blueTemplate.setName(file.getName());
		while (in.ready() && !(str.equals("##endTA"))) {
			str = in.readLine();
			String aux;

			aux = str.substring(str.indexOf("=") + 1).trim();
			if (str.startsWith(("##SubPackage"))) {

				blueTemplate.setNameSubPackage(aux);

			} else if (str.startsWith("##FileExtention")) {
				blueTemplate.setFileExtention(aux);
			} else if (str.startsWith("##Prefix")) {
				blueTemplate.setPrefixFileName(aux);
			} else if (str.startsWith("##Sufix")) {
				blueTemplate.setSufixFileName(aux);
			} else if (str.startsWith("##modiferPackage")) {
				blueTemplate.setModiferPackage(Boolean.parseBoolean(aux));
			}

		}
		in.close();

	}

	public void listFiles(String directoryPath) throws IOException {

		File diretory = new File(directoryPath);
		// array with a list of the files and sub-directories of the current
		// directory
		File[] listAll = diretory.listFiles();

		if (diretory.isDirectory()) {
			if (listAll.length != 0) {
				for (int i = 0; i < listAll.length; i++) {

					if ((listAll[i].isDirectory())
							&& !(listAll[i].getName().equals(".svn"))) {
						listFiles(listAll[i].getAbsolutePath());

					}
					if (listAll[i].isFile()) {
						listFiles.add(listAll[i]);
					}
				}
			} else {
				System.out.println(diretory.getName() + " directory is empty.");
			}

		} else {
			throw new IOException(
					"Stylesheets directory does not exist. Reinstall Iguassu.");
		}
	}

	public XmiPackage getApplication() {
		return Application;
	}

	public void setApplication(XmiPackage application) {
		Application = application;
	}

	public void addTemplate(BlueTemplate template) {
		this.templates.add(template);
	}

	public Velocity getVelocity() {
		return velocity;
	}

	public void setVelocity(Velocity velocity) {
		this.velocity = velocity;
	}

	public ArrayList<BlueTemplate> getTemplates() {
		return templates;
	}

	public void setTemplates(ArrayList<BlueTemplate> listTemplatesRoles) {
		this.templates = listTemplatesRoles;
	}

	public String getTemplatesPath() {
		return templatesPath;
	}

	public void setTemplatesPath(String templatesPath) {
		this.templatesPath = templatesPath;
	}

	public String getOutDir() {
		return outDir;
	}

	public void setOutDir(String outDir) {
		this.outDir = outDir;
	}

        public ArrayList<File> getListFiles() {
        return listFiles;
    }

    public void setListFiles(ArrayList<File> listFiles) {
        this.listFiles = listFiles;
    }


   
}
